package com.example.admin.mybledemo.ota;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import cn.com.heaton.blelibrary.ble.BleLog;

public class FirmwareParser {

    private static final String TAG = "FirmwareParser";
    private static final int DATA_SIZE = 32;

    // 版本信息结构
    public static class VersionInfo {
        public String romVersion;      // ROM版本（4字节十六进制）
        public String softwareVersion; // 软件版本（4字节十六进制）
        public long fileSize;          // 文件大小（KB）
        
        public VersionInfo(String romVersion, String softwareVersion, long fileSize) {
            this.romVersion = romVersion;
            this.softwareVersion = softwareVersion;
            this.fileSize = fileSize;
        }
    }

    public List<OtaBlock> parse(InputStream inputStream) throws IOException {
        List<OtaBlock> otaBlocks = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            int currentAddress = -1;
            StringBuilder dataHexBuilder = new StringBuilder();

            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.startsWith("@")) {
                    // 处理之前的数据块
                    if (currentAddress != -1 && dataHexBuilder.length() > 0) {
                        String dataHex = dataHexBuilder.toString();
                        byte[] data = parseHexString(dataHex);
                        if (data.length > 0) {
                            otaBlocks.add(new OtaBlock(currentAddress, data));
                        }
                        dataHexBuilder.setLength(0);
                    }
                    
                                    // 解析新地址
                try {
                    String addressHex = line.substring(1);
                    // 只取地址部分，忽略后面的数据（空格分隔）
                    if (addressHex.contains(" ")) {
                        addressHex = addressHex.substring(0, addressHex.indexOf(" "));
                    }
                    currentAddress = Integer.parseInt(addressHex, 16);
                } catch (Exception e) {
                    BleLog.e(TAG, "解析地址失败: " + line + ", 错误: " + e.getMessage());
                    continue;
                }
            } else if (line.length() > 0 && !line.startsWith("#") && !line.startsWith(";")) {
                // 累积数据，跳过注释行（以#或;开头）
                // 过滤掉非十六进制字符
                String filteredLine = filterHexCharacters(line);
                if (!filteredLine.isEmpty()) {
                    dataHexBuilder.append(filteredLine);
                }
            }
            }
            
            // 处理最后一个数据块
            if (currentAddress != -1 && dataHexBuilder.length() > 0) {
                String dataHex = dataHexBuilder.toString();
                byte[] data = parseHexString(dataHex);
                if (data.length > 0) {
                    otaBlocks.add(new OtaBlock(currentAddress, data));
                }
            }
        }
        
        return otaBlocks;
    }

    /**
     * 将固件文件解析为行列表（与Flutter端保持一致）
     */
    public List<String> parseToLines(InputStream inputStream) throws IOException {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line.trim());
            }
        }
        return lines;
    }
    
    /**
     * 从固件文件解析版本信息（与Flutter端保持一致）
     * 从第10行读取版本信息
     */
    public VersionInfo parseVersionInfo(InputStream inputStream) throws IOException {
        // 获取文件物理大小（与Flutter端保持一致）
        long filePhysicalSize = 0;
        if (inputStream instanceof java.io.FileInputStream) {
            java.io.FileInputStream fis = (java.io.FileInputStream) inputStream;
            java.nio.channels.FileChannel channel = fis.getChannel();
            filePhysicalSize = channel.size();
            BleLog.d(TAG, "文件物理大小: " + filePhysicalSize + " 字节");
        }
        
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line.trim());
            }
        }
        
        // 从第10行读取版本信息
        if (lines.size() >= 10) {
            String versionLine = lines.get(9); // 第10行（索引9）
            if (versionLine.length() >= 8) {
                try {
                    String romVersion = versionLine.substring(0, 4);      // 前4位是ROM版本
                    String softwareVersion = versionLine.substring(4, 8); // 后4位是软件版本
                    
                    BleLog.d(TAG, "解析版本信息 - ROM: " + romVersion + ", 软件版本: " + softwareVersion);
                    
                    // 修复：使用文件物理大小，与Flutter端保持一致
                    long fileSizeInKB = filePhysicalSize / 1024;
                    
                    BleLog.d(TAG, "版本解析完成，文件物理大小: " + fileSizeInKB + " KB");
                    return new VersionInfo(romVersion, softwareVersion, fileSizeInKB);
                } catch (Exception e) {
                    BleLog.e(TAG, "解析版本信息失败: " + e.getMessage());
                    // 使用文件物理大小
                    long fileSizeInKB = filePhysicalSize / 1024;
                    return new VersionInfo("0000", "0000", fileSizeInKB);
                }
            }
        }
        
        BleLog.w(TAG, "未找到版本信息，使用默认值");
        // 使用文件物理大小
        long fileSizeInKB = filePhysicalSize / 1024;
        return new VersionInfo("0000", "0000", fileSizeInKB);
    }

    /**
     * 从文件行列表解析版本信息
     */
    public VersionInfo parseVersionInfoFromLines(List<String> lines, long filePhysicalSize) {
        BleLog.d(TAG, "开始解析版本信息，文件总行数: " + lines.size() + ", 文件物理大小: " + filePhysicalSize + " 字节");
        
        // 从第11行读取版本信息（第11行包含真正的ROM版本信息）
        if (lines.size() >= 11) {
            String versionLine = lines.get(10); // 第11行（索引10）
            BleLog.d(TAG, "第11行内容: " + versionLine + " (长度: " + versionLine.length() + ")");
            
            if (versionLine.length() >= 8) {
                try {
                    String romVersion = versionLine.substring(0, 4);      // 前4位是ROM版本
                    String softwareVersion = versionLine.substring(4, 8); // 后4位是软件版本
                    
                    BleLog.d(TAG, "解析版本信息 - ROM: " + romVersion + " (长度: " + romVersion.length() + "), 软件版本: " + softwareVersion + " (长度: " + softwareVersion.length() + ")");
                    BleLog.d(TAG, "ROM版本字节: " + romVersion.getBytes().length + ", 软件版本字节: " + softwareVersion.getBytes().length);
                    
                    // 修复：使用文件物理大小，与Flutter端保持一致
                    // Flutter端：OtaManagerEx.instance.softSize = (_otaFile.lengthSync() ~/ 1024).toString();
                    long fileSizeInKB = filePhysicalSize / 1024;
                    
                    BleLog.d(TAG, "版本解析完成，文件物理大小: " + filePhysicalSize + " 字节 = " + fileSizeInKB + " KB");
                    BleLog.d(TAG, "与Flutter端保持一致：使用文件物理大小而不是计算十六进制内容大小");
                    return new VersionInfo(romVersion, softwareVersion, fileSizeInKB);
                } catch (Exception e) {
                    BleLog.e(TAG, "解析版本信息失败: " + e.getMessage());
                    // 如果解析失败，使用文件物理大小
                    long fileSizeInKB = filePhysicalSize / 1024;
                    return new VersionInfo("0000", "0000", fileSizeInKB);
                }
            } else {
                BleLog.e(TAG, "第11行长度不足8位: " + versionLine.length());
            }
        } else {
            BleLog.e(TAG, "文件行数不足11行: " + lines.size());
        }
        
        BleLog.w(TAG, "未找到版本信息，使用默认值");
        // 使用文件物理大小作为默认值
        long fileSizeInKB = filePhysicalSize / 1024;
        return new VersionInfo("0000", "0000", fileSizeInKB);
    }

    /**
     * 解析OTA文件内容（一次性读取所有内容）
     */
    public List<OtaBlock> parseFromLines(List<String> lines) throws IOException {
        List<OtaBlock> otaBlocks = new ArrayList<>();
        int currentAddress = -1;
        StringBuilder dataHexBuilder = new StringBuilder();

        for (String line : lines) {
            line = line.trim();
            if (line.startsWith("@")) {
                // 处理之前的数据块
                if (currentAddress != -1 && dataHexBuilder.length() > 0) {
                    String dataHex = dataHexBuilder.toString();
                    byte[] data = parseHexString(dataHex);
                    if (data.length > 0) {
                        otaBlocks.add(new OtaBlock(currentAddress, data));
                    }
                    dataHexBuilder.setLength(0);
                }
                
                // 解析新地址
                try {
                    String addressHex = line.substring(1);
                    // 只取地址部分，忽略后面的数据（空格分隔）
                    if (addressHex.contains(" ")) {
                        addressHex = addressHex.substring(0, addressHex.indexOf(" "));
                    }
                    currentAddress = Integer.parseInt(addressHex, 16);
                } catch (Exception e) {
                    BleLog.e(TAG, "解析地址失败: " + line + ", 错误: " + e.getMessage());
                    continue;
                }
            } else if (line.length() > 0 && !line.startsWith("#") && !line.startsWith(";")) {
                // 累积数据，跳过注释行（以#或;开头）
                // 过滤掉非十六进制字符
                String filteredLine = filterHexCharacters(line);
                if (!filteredLine.isEmpty()) {
                    dataHexBuilder.append(filteredLine);
                }
            }
        }
        
        // 处理最后一个数据块
        if (currentAddress != -1 && dataHexBuilder.length() > 0) {
            String dataHex = dataHexBuilder.toString();
            byte[] data = parseHexString(dataHex);
            if (data.length > 0) {
                otaBlocks.add(new OtaBlock(currentAddress, data));
            }
        }
        
        return otaBlocks;
    }

    /**
     * 计算文件大小（KB）
     */
    private long calculateFileSize(InputStream inputStream) throws IOException {
        long size = 0;
        byte[] buffer = new byte[1024];
        int bytesRead;
        
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            size += bytesRead;
        }
        
        return size / 1024; // 转换为KB
    }

    private byte[] parseHexString(String hexData) {
        if (hexData == null || hexData.trim().isEmpty()) {
            return new byte[0];
        }
        
        String cleanString = hexData.replaceAll("\\s", "");
        if (cleanString.length() == 0) {
            return new byte[0];
        }
        
        if (cleanString.length() % 2 != 0) {
            BleLog.e(TAG, "无效的十六进制数据: " + hexData);
            return new byte[0];
        }
        
        try {
            byte[] result = new byte[cleanString.length() / 2];
            for (int i = 0; i < cleanString.length(); i += 2) {
                String hexPair = cleanString.substring(i, i + 2);
                result[i / 2] = (byte) Integer.parseInt(hexPair, 16);
            }
            return result;
        } catch (NumberFormatException e) {
            BleLog.e(TAG, "解析十六进制数据失败: " + e.getMessage());
            return new byte[0];
        }
    }

    private static String cleanHexString(String s) {
        if (s == null) {
            return "";
        }
        
        String cleanString = s.replaceAll("\\s", "");
        if (cleanString.length() % 2 != 0) {
            BleLog.e(TAG, "十六进制字符串长度必须为偶数: " + s);
            return "";
        }
        
        // 验证十六进制字符
        for (int i = 0; i < cleanString.length(); i += 2) {
            try {
                Integer.parseInt(cleanString.substring(i, i + 2), 16);
            } catch (NumberFormatException e) {
                BleLog.e(TAG, "无效的十六进制字符: " + cleanString.charAt(i) + cleanString.charAt(i + 1));
                return "";
            }
        }
        
        return cleanString;
    }

    /**
     * 过滤十六进制字符，只保留有效的十六进制字符
     */
    private String filterHexCharacters(String line) {
        if (line == null || line.isEmpty()) {
            return "";
        }
        
        StringBuilder result = new StringBuilder();
        for (char c : line.toCharArray()) {
            if (Character.isDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
                result.append(c);
            }
        }
        return result.toString();
    }

    private static byte[] hexStringToBytes(String s) {
        String cleanString = cleanHexString(s);
        if (cleanString.isEmpty()) {
            return new byte[0];
        }
        
        try {
            byte[] result = new byte[cleanString.length() / 2];
            for (int i = 0; i < cleanString.length(); i += 2) {
                result[i / 2] = (byte) Integer.parseInt(cleanString.substring(i, i + 2), 16);
            }
            return result;
        } catch (NumberFormatException e) {
            BleLog.e(TAG, "解析十六进制数据失败: " + e.getMessage());
            return new byte[0];
        }
    }
}